﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using Debug = UnityEngine.Debug;
using System.Linq;
using System.Security.Cryptography;
using Jing.Net;

/// <summary>
/// 网络的配置参数
/// </summary>
public class NetConst {
    public static string NET_RES_PATH = null; //本地资源下载的路径(即本地资源的存储路径)
}

/// <summary>
/// 下载资源的信息
/// </summary>
public class LoadInfo {
    public List<string> urls;
    public Action beforeLoadCallBack;
    public Action finishCallBack;
    public Action failedCallBack;
    public Action<float> progress;
}

public class HttpDownLoader : MonoBehaviour {

    /// <summary>
    /// 加载的进度
    /// </summary>
    public float DownLoadProgress { get; set; }

    /// <summary>
    /// old进度
    /// </summary>
    private float oldProgress { get; set; }

    private Coroutine download;

    private List<Downloader> downloaders = new List<Downloader> ();

    public static HttpDownLoader Instance;

    private Dictionary<string, string> ResConfigInfos = new Dictionary<string, string> ();

    /// <summary>
    /// 本地缓存的资源配置表
    /// </summary>
    private string ResConfigFile = null;
    private void ReadConfigInfo () {
        Debug.Log ("读取配置文件...");
        if (!Directory.Exists (NetConst.NET_RES_PATH)) {
            Directory.CreateDirectory (NetConst.NET_RES_PATH);
        }
        if (!File.Exists (ResConfigFile)) {
            File.Create (ResConfigFile).Close ();
        }
        string[] data = File.ReadAllLines (ResConfigFile);
        data.ToList ().ForEach (i => {
            ResConfigInfos.Add (i.Split (',') [0], i.Split (',') [1]);
        });
    }

    private void WriteConfigInfo () {
        Debug.Log ("写入配置文件...");
        using (StreamWriter sw = new StreamWriter (ResConfigFile)) {
            ResConfigInfos.Keys.ToList ().ForEach (i => {
                sw.WriteLine (i + "," + ResConfigInfos[i]);
            });
        }
    }

    private void Awake () {
        if (Instance == null) {
            Instance = this;
        }
        NetConst.NET_RES_PATH = Application.persistentDataPath;
        ResConfigFile = NetConst.NET_RES_PATH + "/resconfig.txt";
        ReadConfigInfo ();
    }

    private void OnDestroy () {
        Instance = null;
        WriteConfigInfo ();
    }

    public void StopDownLoad () {
        if (download != null)
            StopCoroutine (download);
        foreach (var item in downloaders) {
            item.Dispose ();
        }
        downloaders.Clear ();
    }

    /// <summary>
    /// 开始下载资源
    /// </summary>
    public void StartDownLoadResources (LoadInfo info) {
        if (info.urls.Count > 0) {
            download = StartCoroutine (DownLoadSaveResources (info));
        }
    }

    /// <summary>
    /// 开始加载本地资源
    /// </summary>
    /// <param name="url">本地资源url</param>
    /// <param name="action">资源下载完成的回调 byte</param>
    public void StartLoadLocalResource (string url, Action<byte[]> action) {
        StartCoroutine (LoadLocalResource (url, action));
    }

    /// <summary>
    /// 下载并且保存资源
    /// </summary>
    private IEnumerator DownLoadSaveResources (LoadInfo info) {
        DownLoadProgress = 0;
        info.beforeLoadCallBack?.Invoke ();
        foreach (var url in info.urls) {
            if (string.IsNullOrEmpty (url)) {
                continue;
            }
            string fileName = md5 (url);
            if (ResConfigInfos.ContainsKey (fileName)) {
                continue;
            }
            Downloader loader = null;
            try {
                loader = new Downloader (url, NetConst.NET_RES_PATH + "/" + fileName);
            } catch (Exception e) {
                Debug.Log ("下载异常:" + e.ToString ());
                info.failedCallBack?.Invoke ();
                continue;
            }
            downloaders.Add (loader);
            while (!loader.isDone) {
                oldProgress = loader.progress;
                //Debug.LogWarning("下载的进度:" + loader.progress);
                yield return new WaitForEndOfFrame ();
                DownLoadProgress += (loader.progress - oldProgress) / info.urls.Count;
                info.progress?.Invoke (DownLoadProgress);
            }
            if (loader.isDone && loader.error == null) {
                Debug.LogWarning ("下载完成");
                ResConfigInfos.Add (fileName, url);
            } else {
                Debug.LogError ("loader.error:" + loader.error + "------" + "请求的地址是：" + url);
                info.failedCallBack?.Invoke ();
            }
            loader.Dispose ();
            downloaders.Remove (loader);
        }
        info.urls.Clear ();
        DownLoadProgress = 1;
        info.finishCallBack?.Invoke ();
    }

    /// <summary>
    /// 加载本地资源
    /// </summary>
    /// <returns></returns>
    private IEnumerator LoadLocalResource (string url, Action<byte[]> action) {
        string file = "file://" + NetConst.NET_RES_PATH + "/" + md5 (url);
        Debug.Log ("加载本地资源的地址是：" + file);
        using (UnityWebRequest webRequest = UnityWebRequest.Get (file)) {
            yield return webRequest.SendWebRequest ();
            if (webRequest.isDone && webRequest.error == null) {
                action?.Invoke (webRequest.downloadHandler.data);
            } else {
                Debug.Log ("加载本地资源错误,webRequest.error:" + webRequest.error + "--" + file);
            }
        }
    }

    /// <summary>
    /// 计算字符串的MD5值
    /// </summary>
    public static string md5 (string source) {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider ();
        byte[] data = System.Text.Encoding.UTF8.GetBytes (source);
        byte[] md5Data = md5.ComputeHash (data, 0, data.Length);
        md5.Clear ();

        string destString = "";
        for (int i = 0; i < md5Data.Length; i++) {
            destString += System.Convert.ToString (md5Data[i], 16).PadLeft (2, '0');
        }
        destString = destString.PadLeft (32, '0');
        //截取其中的16位
        return destString.Substring (0, 16);
    }
}